package adfc2.core;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * Абстрактное существо, выполняющее действия или задачи
 */
public abstract class Creature extends Entity {

    public static enum AiEvent {
        TICK,
        TASK_COMPLETED,
        TASK_FAILED
    }

    public static enum Gender {
        MALE("he"),
        FEMALE("she"),
        BOTH("it"),
        OTHER("it"),
        NONE("it");
        public final String pronoun;

        Gender(String pronoun) {
            this.pronoun = pronoun;
        }
    }

    public Action action;
    public Task task;
    /**
     * Здание, в котором находится существо
     */
    public Entity container;

    public abstract Gender gender();

    private final List<Item> backpack = new LinkedList<Item>();

    public final Item itemLike(Item item, long criteria) {
        for (Item item1 : backpack) {
            if (item1.similar(item, criteria)) return item1;
        }
        return null;
    }

    public final boolean hasItemLike(Item item, long criteria) {
        return itemLike(item, criteria) != null;
    }

    public boolean hasItem(Item item) {
        return backpack.contains(item);
    }

    public List<Item> backpack() {
        return Collections.unmodifiableList(backpack);
    }

    public void startAction(Action action) {
        if (this.action != null) this.action.cancel();
        this.action = action;
    }

    public void startTask(Task task) {
        if (this.task != null) {
            this.task.cancel();
            if (this.action != null) this.action.cancel();
        }
        this.task = task;
    }

    @Override
    public void tick(long dt) {
        if (action != null) {
            action.tick(dt);
            if (action.completed) {
                action = null;
                actionCompleted(action);
            }
        }

        if (task != null) {
            if (action == null) {
                Action next = task.nextAction();
                if (next != null) next.start();
            }
            if (task.completed) {
                ai(AiEvent.TASK_COMPLETED);
                task = null;
            } else if (task.failed) {
                ai(AiEvent.TASK_FAILED);
                task = null;
            }
        }
        ai(AiEvent.TICK);
    }

    protected abstract void ai(AiEvent event, Object... args);

    protected void actionCompleted(Action _action) {
    }

    public void addItem(Item item) {
        assert item.owner == null;
        item.owner = this;
        backpack.add(item);
    }

    public void removeItem(Item item) {
        assert item.owner == this;
        item.owner = null;
        backpack.remove(item);
    }
}
